﻿#include "IntelligentCreatureObject.h"
#include "../MirEnvir/Envir.h"
#include "../../Shared/Globals.h"
#include "../../Shared/Functions/Functions.h"
#include "../../Shared/ServerPackets.h"
#include "../MirEnvir/Map.h"
#include "ItemObject.h"

using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
namespace S = ServerPackets;

namespace Server::MirObjects
{

    std::string IntelligentCreatureObject::getCustomName() const
    {
        return CreatureInfo->CustomName;
    }

    void IntelligentCreatureObject::setCustomName(const std::string &value)
    {
        CreatureInfo->CustomName = value;
    }

    IntelligentCreatureItemFilter *IntelligentCreatureObject::getItemFilter() const
    {
        return CreatureInfo->Filter;
    }

    void IntelligentCreatureObject::setItemFilter(IntelligentCreatureItemFilter *value)
    {
        CreatureInfo->Filter = value;
    }

    IntelligentCreaturePickupMode IntelligentCreatureObject::getCurrentPickupMode() const
    {
        return CreatureInfo->petMode;
    }

    void IntelligentCreatureObject::setCurrentPickupMode(IntelligentCreaturePickupMode value)
    {
        CreatureInfo->petMode = value;
    }

    int IntelligentCreatureObject::getFullness() const
    {
        return CreatureInfo->Fullness;
    }

    void IntelligentCreatureObject::setFullness(int value)
    {
        CreatureInfo->Fullness = value;
    }

    long long IntelligentCreatureObject::getBlackstoneTime() const
    {
        return CreatureInfo->BlackstoneTime;
    }

    void IntelligentCreatureObject::setBlackstoneTime(long long value)
    {
        CreatureInfo->BlackstoneTime = value;
    }

    long long IntelligentCreatureObject::getMaintainfoodTime() const
    {
        return CreatureInfo->MaintainFoodTime;
    }

    void IntelligentCreatureObject::setMaintainfoodTime(long long value)
    {
        CreatureInfo->MaintainFoodTime = value;
    }

    bool IntelligentCreatureObject::getBlocking() const
    {
        return false;
    }

    bool IntelligentCreatureObject::getCanMove() const
    {
        return getEnvir()->getTime() > MoveTime && getEnvir()->getTime() > ActionTime;
    }

    std::string IntelligentCreatureObject::getName() const
    {
        return Master == nullptr ? getCustomName() : (Dead ? getCustomName() : StringHelper::formatSimple("{0}_{1}'s Pet", getCustomName(), Master->getName()));
    }

    void IntelligentCreatureObject::setName(const std::string &value)
    {
        throw NotSupportedException();
    }

    bool IntelligentCreatureObject::getCanAttack() const
    {
        return !Dead && getEnvir()->getTime() > AttackTime && getEnvir()->getTime() > ActionTime;
    }

    ObjectType IntelligentCreatureObject::getRace() const
    {
        return ObjectType::Creature;
    }

    IntelligentCreatureObject::IntelligentCreatureObject(MonsterInfo *info) : MonsterObject(info)
    {
        ActionTime = getEnvir()->getTime() + 1000;
        PetType = static_cast<IntelligentCreatureType>(info->Effect);
    }

    void IntelligentCreatureObject::SetOperateTime()
    {
        MonsterObject::SetOperateTime();

        auto time = OperateTime;

        if (CreatureTime < time && CreatureTime > getEnvir()->getTime())
        {
            time = RoamTime;
        }

        if (OperateTime <= getEnvir()->getTime() || time < OperateTime)
        {
            OperateTime = time;
        }
    }

    void IntelligentCreatureObject::Process()
    {
        RefreshNameColour();

        if (getTarget() != nullptr && (getTarget()->getCurrentMap() != getCurrentMap() || !Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), Globals::DataRange)))
        {
            setTarget(nullptr);
        }

        if (Dead && getEnvir()->getTime() >= DeadTime)
        {
            getCurrentMap()->RemoveObject(this);
            if (Master != nullptr)
            {
                Master->Pets.Remove(this);
                Master = nullptr;
            }

            Despawn();
            return;
        }

        if (getEnvir()->getTime() > CreatureTime)
        {
            CreatureTime = getEnvir()->getTime() + Settings::Second;

            ProcessBlackStoneProduction();
            ProcessMaintainFoodBuff();
        }

        if (getFullness() == 0) //unable to operate with food level 0
        {
            CreatureTimedSay("I'm starving!!.");
            return;
        }

        DecreaseFullness(1); //Decrease Feeding

        if (DoDelayedPickup && getTarget() != nullptr && DoTargetList) //delayed pickup
        {
            if (getEnvir()->getTime() > DelayedpickupTicker)
            {
                PickupAllItems(getTarget()->getCurrentLocation());
                setTarget(nullptr);
                DoDelayedPickup = false;

                if (TargetList.size() > 0)
                {
                    TargetList.erase(TargetList.begin());
                }

                if (TargetList.empty())
                {
                    DoTargetList = false;
                    TargetListTargetClean = false;
                    return;
                }
            }
            else
            {
                return;
            }
        }

        if (DoTargetList) //Semi-auto | mouse pickup
        {
            ProcessTargetList();
            return;
        }

        if (getTarget() == nullptr)
        {
            shortcheck = true;
            FindTarget();
        }

        if (getTarget() == nullptr)
        {
            ProcessAI();
        }
        else
        {
            ProcessTarget();
        }

        ProcessRegen();
    }

    void IntelligentCreatureObject::ProcessAnimVariant()
    {

        if (getEnvir()->getTime() > AnimvariantTicker)
        {
            AnimvariantTicker = getEnvir()->getTime() + AnimvariantDelay;
            ActionTime = getEnvir()->getTime() + 300;
            AttackTime = getEnvir()->getTime() + AttackSpeed;

            switch (PetType)
            {
                case IntelligentCreatureType::BabyDragon:
                case IntelligentCreatureType::OlympicFlame:
                    if (getEnvir()->Random->Next(10) > 5)
                    {
                        S::ObjectAttack *tempVar = new S::ObjectAttack();
                        tempVar->ObjectID = ObjectID;
                        tempVar->Direction = getDirection();
                        tempVar->Location = getCurrentLocation();
                        tempVar->Type = 1;
                        Broadcast(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                    }
                    else
                    {
                        S::ObjectAttack *tempVar2 = new S::ObjectAttack();
                        tempVar2->ObjectID = ObjectID;
                        tempVar2->Direction = getDirection();
                        tempVar2->Location = getCurrentLocation();
                        tempVar2->Type = 2;
                        Broadcast(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
                    }
                    break;
                case IntelligentCreatureType::BabySnowMan:
                    S::ObjectAttack *tempVar3 = new S::ObjectAttack();
                    tempVar3->ObjectID = ObjectID;
                    tempVar3->Direction = getDirection();
                    tempVar3->Location = getCurrentLocation();
                    tempVar3->Type = 1;
                    Broadcast(tempVar3);
                    break;
                default:
                    switch (getEnvir()->Random->Next(10))
                    {
                        case 0:
                            S::ObjectAttack *tempVar4 = new S::ObjectAttack();
                            tempVar4->ObjectID = ObjectID;
                            tempVar4->Direction = getDirection();
                            tempVar4->Location = getCurrentLocation();
                            Broadcast(tempVar4);
                            break;
                        case 1:
                        case 2:
                        case 3:
                            S::ObjectAttack *tempVar5 = new S::ObjectAttack();
                            tempVar5->ObjectID = ObjectID;
                            tempVar5->Direction = getDirection();
                            tempVar5->Location = getCurrentLocation();
                            tempVar5->Type = 1;
                            Broadcast(tempVar5);
                            break;
                        case 4:
                        case 5:
                        case 6:
                            S::ObjectAttack *tempVar6 = new S::ObjectAttack();
                            tempVar6->ObjectID = ObjectID;
                            tempVar6->Direction = getDirection();
                            tempVar6->Location = getCurrentLocation();
                            tempVar6->Type = 2;
                            Broadcast(tempVar6);
                            break;
                        case 7:
                        case 8:
                        case 9:
                            S::ObjectAttack *tempVar7 = new S::ObjectAttack();
                            tempVar7->ObjectID = ObjectID;
                            tempVar7->Direction = getDirection();
                            tempVar7->Location = getCurrentLocation();
                            tempVar7->Type = 3;
                            Broadcast(tempVar7);
                            break;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar7' statement was not added since tempVar7 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar6' statement was not added since tempVar6 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar5' statement was not added since tempVar5 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
                    }
                    break;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
            }
        }
    }

    void IntelligentCreatureObject::ProcessBuffs()
    {
        //bool refresh = false;
        //if (refresh) RefreshAll();
    }

    void IntelligentCreatureObject::ProcessAI()
    {
        if (Dead)
        {
            return;
        }

        if (Master != nullptr)
        {
            if ((Master->getPMode() == PetMode::Both || Master->getPMode() == PetMode::MoveOnly))
            {
                if (!Functions::InRange(getCurrentLocation(), Master->getCurrentLocation(), Globals::DataRange) || getCurrentMap() != Master->getCurrentMap())
                {
                    setTarget(nullptr);
                    PetRecall();
                }
            }
        }

        if (getTarget() == nullptr)
        {
            shortcheck = true;
            FindTarget();
        }
        if (getTarget() == nullptr)
        {
            ProcessSearch();
            ProcessRoam();
        }
        ProcessTarget();
    }

    void IntelligentCreatureObject::ProcessSearch()
    {
        if (getTarget() == nullptr)
        {
            shortcheck = true;
            FindTarget();
        }
        if (getTarget() != nullptr)
        {
            return;
        }
        if (getEnvir()->getTime() < SearchTime)
        {
            return;
        }

        SearchTime = getEnvir()->getTime() + SearchDelay;

        if (getTarget() == nullptr || getEnvir()->Random->Next(3) == 0)
        {
            FindTarget();
        }
    }

    void IntelligentCreatureObject::ProcessRoam()
    {
        if (getTarget() == nullptr)
        {
            FindTarget();
        }
        if (getTarget() != nullptr || getEnvir()->getTime() < RoamTime)
        {
            return;
        }

        //if (ProcessRoute()) return;
        RoamTime = getEnvir()->getTime() + 500;

        if (Master != nullptr)
        {
            if (!Functions::InRange(getCurrentLocation(), Master->getCurrentLocation(), 2))
            {
                MoveTo(Functions::PointMove(Master->getCurrentLocation(),Master->getDirection(), -2));
            }
            else
            {
                if (getEnvir()->Random->Next(100) >= 60)
                {
                    ProcessAnimVariant(); //random anims
                }
            }
        }
    }

    void IntelligentCreatureObject::ProcessTarget()
    {
        if (getTarget() == nullptr || !getCanAttack())
        {
            return;
        }

        if (getTarget()->getCurrentLocation() == getCurrentLocation() || (!CheckAndMoveTo(getTarget()->getCurrentLocation()) && Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), 1)))
        {
            Attack();

            if (getTarget() == nullptr)
            {
                shortcheck = true;
                FindTarget();
            }
            return;
        }
    }

    void IntelligentCreatureObject::FindTarget()
    {
        if (Dead)
        {
            return;
        }

        if (getFullness() < CreatureRules->MinimalFullness)
        {
            return;
        }

        //do automatic pickup/find
        if (CreatureRules->AutoPickupEnabled && getCurrentPickupMode() == IntelligentCreaturePickupMode::Automatic)
        {
            FindItemTarget();
        }
    }

    void IntelligentCreatureObject::FindItemTarget()
    {
        if (Master == nullptr)
        {
            return;
        }

        int range = shortcheck ? 4 : CreatureRules->AutoPickupRange;

        for (int d = 0; d <= range; d++)
        {
            for (int y = getCurrentLocation()->Y - d; y <= getCurrentLocation()->Y + d; y++)
            {
                if (y < 0)
                {
                    continue;
                }
                if (y >= getCurrentMap()->Height)
                {
                    break;
                }

                for (int x = getCurrentLocation()->X - d; x <= getCurrentLocation()->X + d; x += std::abs(y - getCurrentLocation()->Y) == d ? 1 : d * 2)
                {
                    if (x < 0)
                    {
                        continue;
                    }
                    if (x >= getCurrentMap()->Width)
                    {
                        break;
                    }

                    Cell *cell = getCurrentMap()->GetCell(x, y);
                    if (!cell->getValid() || cell->Objects.empty())
                    {
                        continue;
                    }

                    for (int i = 0; i < cell->Objects.size(); i++)
                    {
                        MapObject *ob = cell->Objects[i];
                        if (ob == nullptr)
                        {
                            continue;
                        }
                        if (ob->getRace() != ObjectType::Item)
                        {
                            continue;
                        }
                        if (ob->Owner != nullptr && ob->Owner != this && ob->Owner != Master && !IsMasterGroupMember(ob->Owner))
                        {
                            continue;
                        }

                        ItemObject *item = static_cast<ItemObject*>(ob);
                        if (item->Item != nullptr)
                        {
                            if (!(static_cast<PlayerObject*>(Master))->CanGainItem(item->Item))
                            {
                                continue;
                            }
                            if (CheckItemAgainstFilter(item->Item->Info->Type))
                            {
                                //Master.ReceiveChat("YEAH ITEM I CAN GAIN {" + item.Item.FriendlyName + "} " + item.Item.Info.Type.ToString(), ChatType.System);
                                if (item->Item->Info->Grade >= getItemFilter()->PickupGrade)
                                {
                                    setTarget(ob);
                                }
                                shortcheck = false;
                                return;
                            }
                        }
                        else
                        {
                            if (item->Gold > 0)
                            {
                                if (!(static_cast<PlayerObject*>(Master))->CanGainGold(item->Gold))
                                {
                                    continue;
                                }
                                if (getItemFilter()->PetPickupAll || getItemFilter()->PetPickupGold)
                                {
                                    //Master.ReceiveChat("YEAH GOLD I CAN GAIN {" + item.Gold + "}", ChatType.System);
                                    setTarget(ob);
                                    shortcheck = false;
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
        shortcheck = false;
    }

    bool IntelligentCreatureObject::FillTargetList(Point *location)
    {
        int range = CreatureRules->SemiAutoPickupRange;

        TargetList.clear();
        for (int d = 0; d <= range; d++)
        {
            for (int y = location->Y - d; y <= location->Y + d; y++)
            {
                if (y < 0)
                {
                    continue;
                }
                if (y >= getCurrentMap()->Height)
                {
                    break;
                }

                for (int x = location->X - d; x <= location->X + d; x += std::abs(y - location->Y) == d ? 1 : d * 2)
                {
                    if (x < 0)
                    {
                        continue;
                    }
                    if (x >= getCurrentMap()->Width)
                    {
                        break;
                    }

                    Cell *cell = getCurrentMap()->GetCell(x, y);
                    if (!cell->getValid() || cell->Objects.empty())
                    {
                        continue;
                    }

                    for (int i = 0; i < cell->Objects.size(); i++)
                    {
                        MapObject *ob = cell->Objects[i];
                        if (ob == nullptr)
                        {
                            continue;
                        }
                        if (ob->getRace() != ObjectType::Item)
                        {
                            continue;
                        }
                        if (ob->Owner != nullptr && ob->Owner != this && ob->Owner != Master && !IsMasterGroupMember(ob->Owner))
                        {
                            continue;
                        }

                        ItemObject *item = static_cast<ItemObject*>(ob);
                        if (item->Item != nullptr)
                        {
                            if (!(static_cast<PlayerObject*>(Master))->CanGainItem(item->Item))
                            {
                                continue;
                            }
                            if (CheckItemAgainstFilter(item->Item->Info->Type))
                            {
                                if (item->Item->Info->Grade >= getItemFilter()->PickupGrade)
                                {
                                    TargetList.push_back(ob);
                                }
                                break;
                            }
                        }
                        else
                        {
                            if (item->Gold > 0)
                            {
                                if (!(static_cast<PlayerObject*>(Master))->CanGainGold(item->Gold))
                                {
                                    continue;
                                }
                                if (getItemFilter()->PetPickupAll || getItemFilter()->PetPickupGold)
                                {
                                    TargetList.push_back(ob);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        return (TargetList.size() > 0);
    }

    void IntelligentCreatureObject::ProcessTargetList()
    {
        if (!DoTargetList)
        {
            return;
        }
        if (!getCanAttack())
        {
            return;
        }
        if (TargetList.empty())
        {
            DoTargetList = false;
            TargetListTargetClean = false;
            return;
        }

        bool remove = false;
        if (TargetList[0] == nullptr)
        {
            remove = true;
        }
        if (TargetList[0]->getRace() != ObjectType::Item)
        {
            remove = true;
        }
        if (TargetList[0]->Owner != nullptr && TargetList[0]->Owner != this && TargetList[0]->Owner != Master && !IsMasterGroupMember(TargetList[0]->Owner))
        {
            remove = true;
        }
        if (remove || TargetListTargetClean || TargetList[0]->getCurrentMap() != getCurrentMap())
        {
            TargetList.erase(TargetList.begin());
            TargetListTargetClean = false;
            ProcessTargetList(); //retry
            return;
        }

        setTarget(TargetList[0]);

        if (getTarget()->getCurrentLocation() == getCurrentLocation() || (!CheckAndMoveTo(getTarget()->getCurrentLocation()) && Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), 1)))
        {
            DelayedAttack(500);

            if (getTarget() == nullptr)
            {
                TargetList.erase(TargetList.begin());
                if (TargetList.empty())
                {
                    DoTargetList = false;
                    TargetListTargetClean = false;
                    return;
                }
            }
            return;
        }
    }

    bool IntelligentCreatureObject::CheckAndMoveTo(Point *location)
    {
        if (getCurrentLocation() == location)
        {
            return true;
        }

        bool inRange = Functions::InRange(location, getCurrentLocation(), 1);

        if (inRange)
        {
            if (!getCurrentMap()->ValidPoint(location))
            {
                return false;
            }
            Cell *cell = getCurrentMap()->GetCell(location);
            if (!cell->Objects.empty())
            {
                for (int i = 0; i < cell->Objects.size(); i++)
                {
                    MapObject *ob = cell->Objects[i];
                    if (!ob->getBlocking())
                    {
                        continue;
                    }
                    return false;
                }
            }
        }

        MirDirection dir = Functions::DirectionFromPoint(getCurrentLocation(), location);

        if (Walk(dir))
        {
            return true;
        }

        switch (getEnvir()->Random->Next(2)) //No favour
        {
            case 0:
                for (int i = 0; i < 7; i++)
                {
                    dir = Functions::NextDir(dir);

                    if (Walk(dir))
                    {
                        return true;
                    }
                }
                break;
            default:
                for (int i = 0; i < 7; i++)
                {
                    dir = Functions::PreviousDir(dir);

                    if (Walk(dir))
                    {
                        return true;
                    }
                }
                break;
        }
        return false;
    }

    void IntelligentCreatureObject::Attack()
    {
        bool singleitem = getCurrentPickupMode() == IntelligentCreaturePickupMode::SemiAutomatic ? true : false;
        PickupAllItems(getTarget()->getCurrentLocation());

        if (getTarget()->getCurrentLocation() != getCurrentLocation())
        {
            setDirection(Functions::DirectionFromPoint(getCurrentLocation(), getTarget()->getCurrentLocation()));
        }
        S::ObjectAttack *tempVar = new S::ObjectAttack();
        tempVar->ObjectID = ObjectID;
        tempVar->Direction = getDirection();
        tempVar->Location = getCurrentLocation();
        Broadcast(tempVar);

        setTarget(nullptr);

        ActionTime = getEnvir()->getTime() + 300;
        AttackTime = getEnvir()->getTime() + AttackSpeed;

        DecreaseFullness(1); //use some food for operation
        IncreasePearlProduction();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    bool IntelligentCreatureObject::DelayedAttack(long long delay)
    {
        DelayedPickup(delay);

        if (getTarget()->getCurrentLocation() != getCurrentLocation())
        {
            setDirection(Functions::DirectionFromPoint(getCurrentLocation(), getTarget()->getCurrentLocation()));
        }
        S::ObjectAttack *tempVar = new S::ObjectAttack();
        tempVar->ObjectID = ObjectID;
        tempVar->Direction = getDirection();
        tempVar->Location = getCurrentLocation();
        Broadcast(tempVar);

        ActionTime = getEnvir()->getTime() + 300;
        AttackTime = getEnvir()->getTime() + AttackSpeed;

        DecreaseFullness(1); //use some food for operation
        IncreasePearlProduction();

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
        return true;
    }

    void IntelligentCreatureObject::DelayedPickup(long long delay)
    {
        DelayedpickupTicker = getEnvir()->getTime() + delay;
        DoDelayedPickup = true;
    }

    void IntelligentCreatureObject::PickupAllItems(Point *location)
    {
        if (Dead || Master == nullptr)
        {
            return;
        }

        Cell *cell = getCurrentMap()->GetCell(getTarget()->getCurrentLocation());
        if (!cell->getValid() || cell->Objects.empty())
        {
            return;
        }


        int count = cell->Objects.size();

        for (int i = 0; i < count; i++)
        {
            PickUpItem(getTarget()->getCurrentLocation());
        }
    }

    void IntelligentCreatureObject::PickUpItem(Point *location)
    {
        if (Dead || Master == nullptr)
        {
            return;
        }

        Cell *cell = getCurrentMap()->GetCell(location);
        if (!cell->getValid() || cell->Objects.empty())
        {
            return;
        }
        for (int i = 0; i < cell->Objects.size(); i++)
        {
            MapObject *ob = cell->Objects[i];
            if (ob == nullptr)
            {
                continue;
            }
            if (ob->getRace() != ObjectType::Item)
            {
                continue;
            }
            if (ob->Owner != nullptr && ob->Owner != this && ob->Owner != Master && !IsMasterGroupMember(ob->Owner))
            {
                continue;
            }

            ItemObject *item = static_cast<ItemObject*>(ob);
            if (item == nullptr)
            {
                continue;
            }
            if (item->Item != nullptr)
            {
                if (!(static_cast<PlayerObject*>(Master))->CanGainItem(item->Item))
                {
                    continue;
                }

                if (item->Item->Info->ShowGroupPickup && IsMasterGroupMember(Master))
                {
                    for (int j = 0; j < Master->GroupMembers.size(); j++)
                    {
                        Master->GroupMembers[j]->ReceiveChat(getName() + " Picked up: {" + item->Item->getFriendlyName() + "}", ChatType::Hint);
                    }
                }

                if (item->Item->Info->Grade == ItemGrade::Mythical || item->Item->Info->Grade == ItemGrade::Legendary)
                {
                    Master->ReceiveChat("Pet Picked up: {" + item->Item->getFriendlyName() + "}", ChatType::Hint);
                    S::IntelligentCreaturePickup *tempVar = new S::IntelligentCreaturePickup();
                    tempVar->ObjectID = ObjectID;
                    (static_cast<PlayerObject*>(Master))->Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                }

                (static_cast<PlayerObject*>(Master))->GainItem(item->Item);
                getCurrentMap()->RemoveObject(ob);
                ob->Despawn();
                return;
            }
            else
            {
                if (ob == nullptr)
                {
                    continue;
                }
                if (!(static_cast<PlayerObject*>(Master))->CanGainGold(item->Gold))
                {
                    continue;
                }
                (static_cast<PlayerObject*>(Master))->GainGold(item->Gold);
                getCurrentMap()->RemoveObject(ob);
                ob->Despawn();
                return;
            }
        }
    }

    bool IntelligentCreatureObject::CheckItemAgainstFilter(ItemType iType)
    {
        //dont use this method to check for gold.
        //instaid just do a simple check like -->>      if (ItemFilter.PetPickupAll || ItemFilter.PetPickupGold)
        if (getItemFilter()->PetPickupAll)
        {
            return true;
        }

        switch (iType)
        {
            case ItemType::Nothing: // <---- im not sure if any item will ever hold this ItemType but better to prevent then cure
                return false;
            case ItemType::Weapon:
                return getItemFilter()->PetPickupWeapons;
            case ItemType::Armour:
                return getItemFilter()->PetPickupArmours;
            case ItemType::Helmet:
                return getItemFilter()->PetPickupHelmets;
            case ItemType::Boots:
                return getItemFilter()->PetPickupBoots;
            case ItemType::Belt:
                return getItemFilter()->PetPickupBelts;
            case ItemType::Necklace:
            case ItemType::Bracelet:
            case ItemType::Ring:
                return getItemFilter()->PetPickupAccessories;
            default:
                return getItemFilter()->PetPickupOthers;
        }
    }

    void IntelligentCreatureObject::ManualPickup(bool mousemode, Point *atLocation)
    {
        if (getFullness() < CreatureRules->MinimalFullness)
        {
            return;
        }

        if (CreatureRules->MousePickupEnabled && mousemode)
        {
            FillTargetList(atLocation);
            DoTargetList = true;
            return;
        }

        if (!mousemode && CreatureRules->SemiAutoPickupEnabled && getCurrentPickupMode() == IntelligentCreaturePickupMode::SemiAutomatic)
        {
            FillTargetList(getCurrentLocation());
            DoTargetList = true;
            return;
        }
    }

    void IntelligentCreatureObject::IncreaseFullness(int amount)
    {
        if (getFullness() >= 10000)
        {
            return;
        }
        FullnessTicker = getEnvir()->getTime() + FullnessDelay;
        setFullness(getFullness() + amount);
        if (getFullness() < CreatureRules->MinimalFullness)
        {
            CreatureSay("*Hmmm*");
        }
        else
        {
            CreatureSay("*Burp*");
        }
        if (getFullness() > 10000)
        {
            setFullness(10000);
        }
    }

    void IntelligentCreatureObject::DecreaseFullness(int amount)
    {
        if (getFullness() <= 0 || getMaintainfoodTime() > 0)
        {
            return;
        }

        if (getEnvir()->getTime() > FullnessTicker)
        {
            FullnessTicker = getEnvir()->getTime() + FullnessDelay;
            setFullness(getFullness() - amount);
            if (getFullness() < 0)
            {
                setFullness(0);
            }
            if (getFullness() < CreatureRules->MinimalFullness)
            {
                CreatureTimedSay("*Me Hungry*");
            }
        }
    }

    void IntelligentCreatureObject::IncreasePearlProduction()
    {
        PearlTicker++;

        if (PearlTicker >= PearlProduceCount)
        {
            if (Master != nullptr)
            {
                (static_cast<PlayerObject*>(Master))->IntelligentCreatureProducePearl();
            }

            PearlTicker = 0;
        }
    }

    void IntelligentCreatureObject::ProcessBlackStoneProduction()
    {
        if (!CreatureRules->CanProduceBlackStone)
        {
            return;
        }

        setBlackstoneTime(getBlackstoneTime() + 1);

        if (getBlackstoneTime() >= BlackstoneProduceTime)
        {
            if (Master != nullptr)
            {
                (static_cast<PlayerObject*>(Master))->IntelligentCreatureProduceBlackStone();
            }

            setBlackstoneTime(0);
        }
    }

    void IntelligentCreatureObject::ProcessMaintainFoodBuff()
    {
        if (getMaintainfoodTime() > 0)
        {
            setMaintainfoodTime(getMaintainfoodTime() - 1);

            if (getMaintainfoodTime() < 0)
            {
                setMaintainfoodTime(0);
            }
        }
    }

    void IntelligentCreatureObject::CreatureTimedSay(const std::string &message)
    {
        if (getEnvir()->getTime() > TimedSayTicker)
        {
            CreatureSay(message);
            TimedSayTicker = getEnvir()->getTime() + TimedSayDelay;
        }
    }

    void IntelligentCreatureObject::CreatureSay(const std::string &message)
    {
        if (Master != nullptr)
        {
            message = StringHelper::formatSimple("{0}:{1}", getCustomName(), message);
            (static_cast<PlayerObject*>(Master))->IntelligentCreatureSay(PetType, message);
        }
    }

    void IntelligentCreatureObject::ReceiveChat(const std::string &text, ChatType type)
    {
        if (type == ChatType::WhisperIn)
        {
            CreatureSay("What?");
        }
    }

    bool IntelligentCreatureObject::IsAttackTarget(PlayerObject *attacker)
    {
        return false;
    }

    bool IntelligentCreatureObject::IsAttackTarget(MonsterObject *attacker)
    {
        return false;
    }

    bool IntelligentCreatureObject::IsFriendlyTarget(PlayerObject *ally)
    {
        return true;
    }

    bool IntelligentCreatureObject::IsFriendlyTarget(MonsterObject *ally)
    {
        return true;
    }

    int IntelligentCreatureObject::Attacked(PlayerObject *attacker, int damage, DefenceType type, bool damageWeapon)
    {
        return 0;
    }

    int IntelligentCreatureObject::Attacked(MonsterObject *attacker, int damage, DefenceType type)
    {
        return 0;
    }

    int IntelligentCreatureObject::Struck(int damage, DefenceType type)
    {
        return 0;
    }

    void IntelligentCreatureObject::ApplyPoison(Poison *p, MapObject *Caster, bool NoResist, bool ignoreDefence)
    {
        //FindTarget();
    }

    bool IntelligentCreatureObject::IsMasterGroupMember(MapObject *player)
    {
        if (player->getRace() != ObjectType::Player || Master == nullptr)
        {
            return false;
        }
        return !(static_cast<PlayerObject*>(Master))->GroupMembers.empty() && std::find((static_cast<PlayerObject*>(Master))->GroupMembers.begin(), (static_cast<PlayerObject*>(Master))->GroupMembers.end(), static_cast<PlayerObject*>(player) != (static_cast<PlayerObject*>(Master))->GroupMembers.end());
    }

    void IntelligentCreatureObject::Spawned()
    {
        MonsterObject::Spawned();
        Summoned = true;
        FullnessTicker = getEnvir()->getTime() + FullnessDelay;
        AnimvariantTicker = getEnvir()->getTime() + AnimvariantDelay;
    }

    void IntelligentCreatureObject::Die()
    {
        if (Dead)
        {
            return;
        }

        MonsterObject::Die();

        if (Dead)
        {
            getCurrentMap()->RemoveObject(this);
            Despawn();
            return;
        }
    }

    Packet *IntelligentCreatureObject::GetInfo()
    {
        S::ObjectMonster *tempVar = new S::ObjectMonster();
        tempVar->ObjectID = ObjectID;
        tempVar->Name = getName();
        tempVar->NameColour = NameColour;
        tempVar->Location = getCurrentLocation();
        tempVar->Image = Info->Image;
        tempVar->Direction = getDirection();
        tempVar->Effect = Info->Effect;
        tempVar->AI = Info->AI;
        tempVar->Light = Info->Light;
        tempVar->Dead = Dead;
        tempVar->Skeleton = Harvested;
        tempVar->Poison = CurrentPoison;
        tempVar->Hidden = getHidden();
        tempVar->Extra = Summoned;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was used in a 'return' or 'throw' statement.
        return tempVar;
    }
}
